﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using AppFx.ComponentModel.Descriptive;
using AppFx.ComponentModel;

namespace Tests.ComponentModel.Descriptive.DescriptionProviders
{
	/// <summary>
	///Dies ist eine Testklasse für "DeepCompiledTypeDescriptionProvider" und soll
	///alle DeepCompiledTypeDescriptionProvider Komponententests enthalten.
	///</summary>
	[TestClass]
	public class Test_DeepCompiledTypeDescriptionProvider
	{
		private Test_ITypeDescriptionProvider _Test;

		/// <summary>
		///Ein Test für "DeepCompiledTypeDescriptionProvider-Konstruktor"
		///</summary>
		[TestMethod()]
		[TestInitialize]
		[Description("Testet, ob der DeepCompiledTypeDescriptionProvider erstellt werden kann.")]
		public void CompiledTypeDescriptionProviderConstructorTest()
		{
			_Test = new Test_ITypeDescriptionProvider();
			_Test.Provider = new DeepCompiledTypeDescriptionProvider();
		}

		/// <summary>
		///Ein Test für "GetDescriptors"
		///</summary>
		[TestMethod()]
		[Description("Testet, ob der DeepCompiledTypeDescriptionProvider PropertyDescriptors auf Basis einer Objektinstanz zur Verfügung stellen kann.")]
		public void Can_GetDescriptorsByInstanceTest()
		{
			_Test.Can_GetDescriptorsByInstanceTest();
		}

		/// <summary>
		///Ein Test für "GetDescriptors"
		///</summary>
		[TestMethod()]
		[Description("Testet, ob der DeepCompiledTypeDescriptionProvider PropertyDescriptors auf Basis eines Typs zur Verfügung stellen kann.")]
		public void Can_GetDescriptorsByTypeTest()
		{
			_Test.Can_GetDescriptorsByTypeTest();
		}

		/// <summary>
		///Ein Test für "GetDescriptors"
		///</summary>
		[TestMethod()]
		[Description("Testet, ob der DeepCompiledTypeDescriptionProvider PropertyDescriptors auf Basis eines Typs zur Verfügung stellen kann, und dabei die übergebene Exclusion berücksichtigt.")]
		public void Can_GetDescriptorsByTypeExclusion()
		{
			_Test.Can_GetDescriptorsByTypeExclusion();
		}

		/// <summary>
		///Ein Test für "GetDescriptors"
		///</summary>
		[TestMethod()]
		[Description("Testet, ob der DeepCompiledTypeDescriptionProvider PropertyDescriptors auf Basis einer Onjektinstanz zur Verfügung stellen kann, und dabei die übergebene Exclusion berücksichtigt.")]
		public void Can_GetDescriptorsByInstanceExclusions()
		{
			_Test.Can_GetDescriptorsByInstanceExclusions();
		}

		/// <summary>
		///Ein Test für "GetDescriptors"
		///</summary>
		[TestMethod()]
		[Description("Testet, ob der DeepCompiledTypeDescriptionProvider PropertyDescriptors auf Basis eines Typs zur Verfügung stellen kann, und dabei alle Exclusions berücksichtigt.")]
		public void Can_GetDescriptorsByTypeExclusions()
		{
			_Test.Can_GetDescriptorsByTypeExclusions();
		}

		/// <summary>
		///Ein Test für "GetDescriptors"
		///</summary>
		[TestMethod()]
		[Description("Testet, ob der DeepCompiledTypeDescriptionProvider PropertyDescriptors auf Basis einer Objektinstanz zur Verfügung stellen kann, und dabei alle Exclusions berücksichtigt.")]
		public void Can_GetDescriptorsByInstanceExclusion()
		{
			_Test.Can_GetDescriptorsByInstanceExclusion();
		}
		
		/// <summary>
		///Ein Test für "GetDescriptors"
		///</summary>
		[TestMethod()]
		[Description("Testet, oder DeepCompiledTypeDescriptionProvider bei der Erstellung von PropertyDescriptors die Setzung des ExlcudeComplexTypes-Properties berücksichtigt.")]
		public void Can_ConsiderExcludeComplexTypesProperty()
		{
			DeepCompiledTypeDescriptionProvider provider = new DeepCompiledTypeDescriptionProvider();
			provider.ExcludeComplexTypes = true;
			Assert.IsFalse(provider.GetDescriptors(typeof(ComplexType)).Where(p => p.Name == "Simple").Count() > 0);
			provider.ExcludeComplexTypes = false;
			Assert.IsTrue(provider.GetDescriptors(typeof(ComplexType)).Where(p => p.Name == "Simple").Count() > 0);
		}

		/// <summary>
		///Ein Test für "GetDescriptors"
		///</summary>
		[TestMethod()]
		[Description("Testet, oder DeepCompiledTypeDescriptionProvider bei der Erstellung von PropertyDescriptors die Nutzung des ExpandableAttributes berücksichtigt.")]
		public void Can_ConsiderExpandableAttribute()
		{
			DeepCompiledTypeDescriptionProvider provider = new DeepCompiledTypeDescriptionProvider();
			IList<System.ComponentModel.PropertyDescriptor> desciptors = provider.GetDescriptors(typeof(ComplexType));
			Assert.IsTrue(desciptors.Where(p => p.Name == "Simple.Title").Count() > 0);
			Assert.IsTrue(desciptors.Where(p => p.Name == "Simple.Name").Count() > 0);
			Assert.IsTrue(desciptors.Where(p => p.Name == "Simple.LastName").Count() > 0);
			Assert.IsTrue(desciptors.Where(p => p.Name == "SimpleExpandable1.Title").Count() > 0);
			Assert.IsTrue(desciptors.Where(p => p.Name == "SimpleExpandable1.Name").Count() > 0);
			Assert.IsTrue(desciptors.Where(p => p.Name == "SimpleExpandable1.LastName").Count() > 0);
			Assert.IsTrue(desciptors.Where(p => p.Name == "SimpleExpandable2.Title").Count() > 0);
			Assert.IsTrue(desciptors.Where(p => p.Name == "SimpleExpandable2.Name").Count() > 0);
			Assert.IsTrue(desciptors.Where(p => p.Name == "SimpleExpandable2.LastName").Count() > 0);
			Assert.IsFalse(desciptors.Where(p => p.Name == "SimpleExpandable3.Title").Count() > 0);
			Assert.IsFalse(desciptors.Where(p => p.Name == "SimpleExpandable3.Name").Count() > 0);
			Assert.IsFalse(desciptors.Where(p => p.Name == "SimpleExpandable3.LastName").Count() > 0);
		}

		/// <summary>
		///Ein Test für "GetDescriptors"
		///</summary>
		[TestMethod()]
		[Description("Testet, oder DeepCompiledTypeDescriptionProvider bei der Erstellung von PropertyDescriptors die Nutzung des IncludeAttributes berücksichtigt.")]
		public void Can_ConsiderIncludeAttribute()
		{
			DeepCompiledTypeDescriptionProvider provider = new DeepCompiledTypeDescriptionProvider();
			provider.ExcludeComplexTypes = true;
			IList<System.ComponentModel.PropertyDescriptor> desciptors = provider.GetDescriptors(typeof(ComplexType));
			Assert.IsFalse(desciptors.Where(p => p.Name == "Simple").Count() > 0);
			Assert.IsFalse(desciptors.Where(p => p.Name == "SimpleExpandable1").Count() > 0);
			Assert.IsTrue(desciptors.Where(p => p.Name == "SimpleExpandable2").Count() > 0);
			Assert.IsFalse(desciptors.Where(p => p.Name == "SimpleExpandable3").Count() > 0);

			provider.ExcludeComplexTypes = false;
			desciptors = provider.GetDescriptors(typeof(ComplexType));
			Assert.IsTrue(desciptors.Where(p => p.Name == "Simple").Count() > 0);
			Assert.IsTrue(desciptors.Where(p => p.Name == "SimpleExpandable1").Count() > 0);
			Assert.IsTrue(desciptors.Where(p => p.Name == "SimpleExpandable2").Count() > 0);
			Assert.IsFalse(desciptors.Where(p => p.Name == "SimpleExpandable3").Count() > 0);
		}
	}

	public class ComplexType
	{
		public int ID { get; set; }

		public SimpleType Simple { get; set; }

		public SimpleType SimpleExpandable1 { get; set; }

		[Expandable(true)]
		[Include(true)]
		public SimpleType SimpleExpandable2 { get; set; }

		[Expandable(false)]
		[Include(false)]
		public SimpleType SimpleExpandable3 { get; set; }
	}

	public class SimpleType
	{
		public string Title { get; set; }

		public string Name { get; set; }

		public string LastName { get; set; }
	}
}
